﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using DBFile.Core.Interfaces;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace DBFile.Providers.Impl
{
    internal class AzureBlobStorage : IDBFileProvider
    {
        private CloudStorageAccount accountInfo;
        private CloudBlobClient blobStorage;
        private CloudBlobContainer blobContainer;

        public AzureBlobStorage(string accountName, string accountSharedKey, string blobStorageEndpoint, bool isPrivateContainer)
        {
            if (accountName == "devstoreaccount1")
            {
                accountInfo = CloudStorageAccount.DevelopmentStorageAccount;
            }
            else
            {
                accountInfo = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountSharedKey), false);
            }
                        
            blobStorage = accountInfo.CreateCloudBlobClient();
            blobStorage.RetryPolicy = RetryPolicies.Retry(2, RetryPolicies.DefaultMinBackoff);
            
            blobContainer = blobStorage.GetContainerReference("dbfile");

            EnsureBlobContainer(isPrivateContainer);

        }

        private void EnsureBlobContainer(bool isPrivateContainer)
        {
            blobContainer.CreateIfNotExist();

            BlobContainerPermissions permissions = blobContainer.GetPermissions();
            if (isPrivateContainer)
            {
                permissions.PublicAccess = BlobContainerPublicAccessType.Off;
            }
            else
            {
                permissions.PublicAccess = BlobContainerPublicAccessType.Container;
            }
            blobContainer.SetPermissions(permissions);
        }

        #region IDBFileProvider Members

        public int Copy(string sourceFilename, string destinationFilename, bool overwrite)
        {
            try
            {
                CloudBlob blob = blobContainer.GetBlobReference(sourceFilename);
                CloudBlob newBlob = blobContainer.GetBlobReference(destinationFilename);

                newBlob.CopyFromBlob(blob);
            }
            catch
            {
                return 0;
            }
            return 1;            
        }


        public int Delete(string filename)
        {
            CloudBlob blob = blobContainer.GetBlobReference(filename);
            bool result = blob.DeleteIfExists();

            return Convert.ToInt32(result);
        }

        public bool Exists(string filename)
        {
            return blobContainer.ListBlobs().Count(b => b.Uri.ToString() == blobContainer.Uri.ToString() + "/" + filename) > 0;
        }

        public T Get<T>(string filename) where T : IDBFile, new()
        {
            CloudBlob blob = blobContainer.GetBlobReference(filename);

            T result = new T();
            result.ContentType = blob.Properties.ContentType;
            result.ContentLength = blob.Properties.Length;
            result.FileName = filename;

            int length = (int)blob.Properties.Length;
            result.FileBytes = new byte[length];
            Array.Copy(blob.DownloadByteArray(), result.FileBytes, length);

            return result;
        }

        public string[] GetFileNameList()
        {
            List<string> result = new List<string>();

            foreach (IListBlobItem blob in blobContainer.ListBlobs())
            {
                result.Add(Path.GetFileName(blob.Uri.ToString()));
            }

            return result.ToArray(); ;
        }

        public int Insert(string filename, byte[] buffer, string contentType, long contentLength)
        {
            try
            {
                CloudBlob blob = blobContainer.GetBlobReference(filename);
                blob.Properties.ContentType = contentType;

                blob.UploadByteArray(buffer);
            }
            catch
            {
                return 0;
            }
            return 1;
        }

        public int Insert(string filename, byte[] buffer, string contentType, long contentLength, bool overwrite)
        {
            CloudBlob blob = blobContainer.GetBlobReference(filename);

            if (!overwrite && blob.Properties.Length > 0)
            {
                return 0;
            }

            return Insert(filename, buffer, contentType, contentLength);
        }

        public int Update(string filename, byte[] buffer, string contentType, long contentLength)
        {
            return Insert(filename, buffer, contentType, contentLength);
        }

        #endregion
    }
}
